package cn.honqun.tinycms.service.impl;

import cn.honqun.tinycms.FileObjectNotFoundException;
import cn.honqun.tinycms.common.exce.ApplicationException;
import cn.honqun.tinycms.domain.entity.FileObject;
import cn.honqun.tinycms.service.AbstractFileObjectService;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.file.FileNameUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.StrUtil;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;

public class FileObjectServiceLocal extends AbstractFileObjectService {

    @Override
    public FileObject create(MultipartFile file) {
        //保存文件到本地
        String uri = this.saveFile(file);
        //构建URL
        String url = fileObjectProperties.getHost() + StrUtil.SLASH + uri;

        FileObject fileObject = new FileObject();
        fileObject.setUrl(url);
        fileObject.setUri(uri);
        fileObject.setSize(file.getSize());
        fileObject.setSizeText(FileUtil.readableFileSize(file.getSize()));
        fileObject.setOriginalName(file.getOriginalFilename());
        fileObjectMapper.insert(fileObject);

        return fileObject;
    }

    @Override
    public void remove(String url) {
        FileObject fileObject = selectByKey(url);
        if (fileObject == null) {
            throw new FileObjectNotFoundException();
        }
        //删除数据
        fileObjectMapper.delete(fileObject);
        //删除文件
        String pathname = fileObjectProperties.getLocal() + StrUtil.SLASH + fileObject.getUri();//完整的文件名
        File file = new File(pathname);
        if (!file.delete()) {
            throw new ApplicationException("删除文件失败");
        }
        //删除缓存
        getCache().remove(getCacheURI(url));
    }

    @Override
    public void read(String url, OutputStream out) {
        FileObject fileObject = selectByKey(url);

        if (fileObject == null) {
            throw new FileObjectNotFoundException();
        }
        //完整的文件名
        String pathname = fileObjectProperties.getLocal() + StrUtil.SLASH + fileObject.getUri();
        File file = new File(pathname);
        if (!file.exists()) {
            throw new FileObjectNotFoundException();
        }
        //读取文件
        try (InputStream in = new BufferedInputStream(new FileInputStream(file))) {
            FileCopyUtils.copy(in, out);
        } catch (IOException e) {
            throw new ApplicationException(e);
        }
    }

    /**
     * 保存文件，返回保存文件的相对路径
     */
    private String saveFile(MultipartFile multipartFile) {
        //扩展名
        String extName = FileNameUtil.extName(multipartFile.getOriginalFilename());
        //文件目录，如果不存在，则创建
        String pathname = createFileDirectoryIfNotExists();
        //这里吧文件名作为URI
        String uri = UUID.fastUUID().toString() + StrUtil.DOT + extName;
        String fullPath = pathname + uri; //完整的文件名
        //存储文件
        try (OutputStream out = new BufferedOutputStream(new FileOutputStream(fullPath))) {
            FileCopyUtils.copy(multipartFile.getInputStream(), out);
        } catch (IOException e) {
            throw new ApplicationException(e);
        }

        return uri;
    }

    /**
     * 返回文件目录，如果不存在则创建
     *
     * @return 文件目录，以/结尾
     */
    private String createFileDirectoryIfNotExists() {
        //文件目录，如果不存在，则创建
        String pathname = fileObjectProperties.getLocal() + StrUtil.SLASH;
        File path = new File(pathname);
        if (!path.exists()) {
            if (!path.mkdirs()) {
                throw new ApplicationException("无法创建文件存储目录" + pathname);
            }
        }
        return pathname;
    }
}
